package com.tanhua.app.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.tanhua.api.db.UserInfoApi;
import com.tanhua.api.mongo.CommentApi;
import com.tanhua.api.mongo.PublishApi;
import com.tanhua.app.interceptor.UserHolder;
import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.mongo.Comment;
import com.tanhua.domain.mongo.Publish;
import com.tanhua.domain.vo.PageBeanVo;
import com.tanhua.domain.vo.PublishVo;
import com.tanhua.util.RelativeDateFormat;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class QuanziService {

    @Reference
    private PublishApi publishApi;

    @Autowired
    private OssTemplate ossTemplate;

    @Reference
    private UserInfoApi userInfoApi;

    @Reference
    private CommentApi commentApi;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired
    private QuanziMQService quanziMQService;

    public void publishMovements(Publish publish, MultipartFile[] imageContent) throws IOException {

        // 1、指定用户id
        publish.setUserId(UserHolder.getUserId());
        // 2、默认未审核
        publish.setState(0);

        // 3、将图片上传到阿里云OSS
        List<String> medias = new ArrayList<>();
        if (imageContent != null) {
            for (MultipartFile file : imageContent) {
                String imgUrl = ossTemplate.upload(file.getOriginalFilename(), file.getInputStream());
                medias.add(imgUrl);
            }
            // 将图片路径设置到publish中
            publish.setMedias(medias);
        }

        // 4、调用api保存动态
        publishApi.save(publish);

        // 使用mq发送一条审核消息
        rocketMQTemplate.convertAndSend("tanhua-publish", publish.getId().toHexString());

        // 使用mq发送大数据圈子消息
        quanziMQService.publishMsg(publish.getId().toHexString());
    }

    public ResponseEntity findAlbumByPage(Integer pageNum, Integer pageSize, Long userId) {
        // 1、调用api查询动态分页对象
        PageBeanVo pageBeanVo = publishApi.findAlbumByPage(pageNum, pageSize, userId);

        // 2、遍历动态详情，封装publishVo
        List<PublishVo> voList = new ArrayList<>();
        List<Publish> publishList = (List<Publish>) pageBeanVo.getItems();
        if (CollectionUtil.isNotEmpty(publishList)) {
            for (Publish publish : publishList) {
                PublishVo vo = new PublishVo();
                // 3、根据用户id查询userInfo
                UserInfo userInfo = userInfoApi.findByUserId(publish.getUserId());
                // 4、封装userInfo到vo中
                BeanUtil.copyProperties(userInfo, vo);
                if (StrUtil.isNotEmpty(userInfo.getTags())) {
                    vo.setTags(userInfo.getTags().split(","));  // 用户标签
                }
                // 5、封装publish到vo中
                BeanUtil.copyProperties(publish, vo);
                if (CollectionUtil.isNotEmpty(publish.getMedias())) {
                    vo.setImageContent(publish.getMedias().toArray(new String[]{})); // 动态图片
                }
                vo.setCreateDate(RelativeDateFormat.format(new Date(publish.getCreated()))); // 动态发布时间
                vo.setDistance("距离1.2公里");

                voList.add(vo); // 加入到集合中
            }
        }

        // 6、设置vo到分页中
        pageBeanVo.setItems(voList);
        // 7、返回分页
        return ResponseEntity.ok(pageBeanVo);
    }

    // 好友动态
    public ResponseEntity findTimeLineByPage(Integer pageNum, Integer pageSize) {
        // 1、查询动态详情
        PageBeanVo pageBeanVo = publishApi.findTimeLineByPage(pageNum, pageSize, UserHolder.getUserId());

        List<PublishVo> voList = new ArrayList<>();
        List<Publish> publishList = (List<Publish>) pageBeanVo.getItems();

        if (CollectionUtil.isNotEmpty(publishList)) {
            for (Publish publish : publishList) {
                PublishVo vo = new PublishVo();
                // 2、userInfo封装到 vo
                UserInfo userInfo = userInfoApi.findByUserId(publish.getUserId());
                vo.setUserInfo(userInfo);
                // 3、publish封装到 vo
                vo.setPublish(publish);
                // 4、是否点赞
                if (stringRedisTemplate.hasKey(StrUtil.format("publish_like_comment_{}_{}", UserHolder.getUserId(), publish.getId()))) {
                    vo.setHasLiked(1);
                } else {
                    vo.setHasLiked(0);
                }
                // 5、vo加入集合中
                voList.add(vo);
            }
        }

        // 6、分页使用voList
        pageBeanVo.setItems(voList);

        return ResponseEntity.ok(pageBeanVo);
    }

    // 从redis中查询圈子
    public PageBeanVo findRecommendByRedis(Integer pageNum, Integer pageSize) {
        PageBeanVo pageBeanVo = null;
        // 1、拼接redis中key
        String key = "QUANZI_PUBLISH_RECOMMEND_" + UserHolder.getUserId();
        // 2、从redis中获取数据
        String value = stringRedisTemplate.opsForValue().get(key);
        // 3、如果redis存在，取出pid
        if (StrUtil.isNotEmpty(value)) {
            String[] pids = value.split(",");// 10015,100092,18,20011,20,20,22,20009,20008,23....... 上百条

            // redis中没有分页功能，需要我们自己计算 起始值和结束值
            Integer startIndex = (pageNum -1)* pageSize; // 起始值
            if (startIndex < pids.length) { //起始条数大于数据总数
                Integer endIndex = startIndex + pageSize - 1;
                if (endIndex >= pids.length) {
                    endIndex = pids.length - 1;
                }
                List<Long> pidList = new ArrayList<>();   //本页查询的所有动态的pid列表
                for (int i = startIndex; i <= endIndex; i++) {
                    pidList.add(Long.valueOf(pids[i]));
                }
                // 根据pid调用publishAPI查询动态信息
                List<Publish> publishList = publishApi.findByPids(pidList);
                long counts = ((Integer) pids.length).longValue();
                pageBeanVo = new PageBeanVo(pageNum, pageSize, counts, publishList);
            }
        }

        return pageBeanVo;
    }

    // 推荐动态
    public ResponseEntity findRecommendByPage(Integer pageNum, Integer pageSize) {

        // a、先查询redis中是否有该用户的推荐动态
        PageBeanVo pageBeanVo = findRecommendByRedis(pageNum, pageSize);
        if (pageBeanVo == null) {
            // b、如果没有再查询mongoDB中热门圈子,调用api查询动态详情
            pageBeanVo = publishApi.findRecommendByPage(pageNum, pageSize, UserHolder.getUserId());
        }

        List<PublishVo> voList = new ArrayList<>();
        List<Publish> publishList = (List<Publish>) pageBeanVo.getItems();

        if (CollectionUtil.isNotEmpty(publishList)) {
            for (Publish publish : publishList) {
                PublishVo vo = new PublishVo();

                // 2、userInfo封装vo
                UserInfo userInfo = userInfoApi.findByUserId(publish.getUserId());
                vo.setUserInfo(userInfo);

                // 3、publish封装vo
                vo.setPublish(publish);

                // 4、是否点赞
                if (stringRedisTemplate.hasKey(StrUtil.format("publish_like_comment_{}_{}", UserHolder.getUserId(), publish.getId()))) {
                    vo.setHasLiked(1);
                } else {
                    vo.setHasLiked(0);
                }

                // 5、是否喜欢
                if (stringRedisTemplate.hasKey(StrUtil.format("publish_love_comment_{}_{}", UserHolder.getUserId(), publish.getId()))) {
                    vo.setHasLoved(1);
                } else {
                    vo.setHasLoved(0);
                }

                // 6、将vo添加到集合中
                voList.add(vo);
            }
        }

        // 7、将voList添加到pageBean中
        pageBeanVo.setItems(voList);

        return ResponseEntity.ok(pageBeanVo);
    }

    public ResponseEntity likePublish(String publishId) {

        // 1、调用api保存comment对象
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(publishId)); // 指定动态id
        comment.setUserId(UserHolder.getUserId()); // 指定点赞人
        comment.setCommentType(1); //评论类型： 1 点赞 2 评论 3 喜欢
        comment.setPubType(1); // 动态类型：  1 动态  2 小视频  3 评论
        Integer total = commentApi.save(comment);

        // 2、向redis中存储对此动态点赞记录
        stringRedisTemplate.opsForValue().set(StrUtil.format("publish_like_comment_{}_{}", UserHolder.getUserId(), publishId), "1");

        // 使用mq发送大数据圈子消息
        quanziMQService.likePublishMsg(publishId);
        return ResponseEntity.ok(total);
    }

    public ResponseEntity dislikePublish(String publishId) {
        // 1、调用api删除点赞记录
        Comment comment = new Comment();
        comment.setUserId(UserHolder.getUserId()); // 用户id
        comment.setPublishId(new ObjectId(publishId)); // 动态id
        comment.setCommentType(1);// 点赞
        Integer total = commentApi.remove(comment);

        // 2、删除redis缓存
        stringRedisTemplate.delete(StrUtil.format("publish_like_comment_{}_{}", UserHolder.getUserId(), publishId));

        // 使用mq发送大数据圈子消息
        quanziMQService.disLikePublishMsg(publishId);
        return ResponseEntity.ok(total);
    }

    public ResponseEntity lovePublish(String publishId) {
        // 1、创建comment对象
        Comment comment = new Comment();
        comment.setUserId(UserHolder.getUserId());
        comment.setPublishId(new ObjectId(publishId));
        comment.setCommentType(3);// 评论类型   1、点赞  2、评论   3、喜欢
        comment.setPubType(1); // 动态类型  1、圈子，2：视频，3：评论

        // 2、保存并返回点赞数量
        Integer total = commentApi.save(comment);

        // 4、将点赞记录存储到redis中
        stringRedisTemplate.opsForValue().set(StrUtil.format("publish_love_comment_{}_{}", UserHolder.getUserId(), publishId), "1");

        // 使用mq发送大数据圈子消息
        quanziMQService.lovePublishMsg(publishId);
        return ResponseEntity.ok(total);

    }

    public ResponseEntity unlovePublish(String publishId) {
        // 1、 创建comment对象，设置删除属性
        Comment comment = new Comment();
        comment.setUserId(UserHolder.getUserId());
        comment.setPublishId(new ObjectId(publishId));
        comment.setCommentType(3);

        // 2、调用api删除
        Integer total = commentApi.remove(comment);

        // 3、删除redis缓存
        stringRedisTemplate.delete(StrUtil.format("publish_love_comment_{}_{}", UserHolder.getUserId(), publishId));

        // 使用mq发送大数据圈子消息
        quanziMQService.disLovePublishMsg(publishId);
        return ResponseEntity.ok(total);
    }

    public ResponseEntity findPublishVoById(String publishId) {
        // 1、调用api查询
        Publish publish = publishApi.findById(publishId);

        // 2、userInfo  + publish  = vo
        PublishVo vo = new PublishVo();
        UserInfo userInfo = userInfoApi.findByUserId(publish.getUserId());

        vo.setUserInfo(userInfo);

        vo.setPublish(publish);

        // 使用mq发送大数据圈子消息
        quanziMQService.queryPublishMsg(publishId);

        return ResponseEntity.ok(vo);
    }
}
